package app.pool.utils;

import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class FileContentUtils {

    /**
     * 从数组中,删除片段
     *
     * @param array
     * @param parts
     * @return
     */
    public static byte[] deleteFileContent(byte[] array, FileParts parts) {
        FileParts leaveParts = parts.calcLeaveParts(array.length);
        return leaveParts.combineFilePartsContent(array);
    }

    /**
     * 将已删除片段,还原到数据中
     *
     * @param array
     * @param parts
     * @return
     */
    public static byte[] restoreDeletedFileContent(byte[] array, FileParts parts) {
        return parts.restoreFileContent(array);
    }

    public static class FileParts {
        private List<FilePart> fileParts;

        public FileParts(List<FilePart> fileParts) {
            Collections.sort(fileParts);
            this.fileParts = fileParts;
        }

        public int allFilePartLength() {
            int length = 0;
            for (FilePart filePart : fileParts) {
                length += filePart.getLength();
            }
            return length;
        }

        public List<FilePart> getFileParts() {
            return fileParts;
        }

        public FileParts calcLeaveParts(int length) {

            List<FilePart> newfileParts = new ArrayList<>();

            int end = 0;

            for (FilePart filePart : this.fileParts) {
                if (filePart.start > end) {
                    FilePart newFilePart = new FilePart();
                    newFilePart.setStart(end);
                    newFilePart.setLength(filePart.start - end);
                    newfileParts.add(newFilePart);
                }

                end = filePart.start + filePart.length;
            }

            if (length > end) {
                FilePart newFilePart = new FilePart();
                newFilePart.setStart(end);
                newFilePart.setLength(length - end);
                newfileParts.add(newFilePart);
            }

            return new FileParts(newfileParts);
        }

        public byte[] combineFilePartsContent(byte[] array) {
            byte[] newarray = new byte[this.allFilePartLength()];
            int destPos = 0;
            for (FilePart filePart : this.fileParts) {
                System.arraycopy(array, filePart.start, newarray, destPos, filePart.getLength());
                destPos += filePart.getLength();
            }
            return newarray;
        }

        public byte[] restoreFileContent(byte[] array) {
            byte[] newarray = new byte[array.length + this.allFilePartLength()];

            // 文件内容增长的长度
            int filelengthInc = 0;

            int copied = 0;
            for (FilePart filePart : this.fileParts) {
                if (filePart.getStart() > copied) {
                    int length = filePart.getStart() - copied;
                    System.arraycopy(array, copied - filelengthInc, newarray, copied, length);
                    copied += length;
                }

                System.arraycopy(filePart.data, 0, newarray, copied, filePart.getLength());
                copied += filePart.getLength();

                filelengthInc += filePart.getLength();
            }

            if (newarray.length > copied) {
                int length = newarray.length - copied;
                System.arraycopy(array, copied - filelengthInc, newarray, copied, length);
            }

            return newarray;
        }
    }

    @Getter
    @Setter
    public static class FilePart implements Comparable<FilePart> {
        private int start;
        private int length;
        private byte[] data;

        @Override
        public int compareTo(FilePart filePart) {
            if (this.start > filePart.start) {
                return 1;
            } else if (this.start == filePart.start) {
                return 0;
            } else {
                return -1;
            }
        }
    }

}
